// 引入库头文件

#include <fstream>

//#include <iostream.h> // 头文件有扩展名时可以不用namespace

#include <iostream> // 预处理器编译指令，include
					// C++的头文件可以是.h的或无扩展名，C语言的是.h的

// 条件编译，只有在windows系统下才引入 windows.h 头文件
// 在函数内部也可以用条件编译
#ifdef _WIN32 
#include <windows.h>
#define _CRT_SECURE_NO_WARNINGS // 使用了strcpy,scanf等不安全的函数，加上后编译不报错，只会在该文件里起作用
#endif

// windows和vs都使用utf8编码
// 引入各类的头文件

// 自定义头文件在main方法中引入
// .h头文件会报错，报无法解析的外部符号，但cpp的可以
// vs自动生成的类可以导入.h文件
//#include"test11_binary_tree.h" // 同时引入.cpp和.h会引起重复编译的错误

#include"test01_Namespace.h"
#include"test02_MinExample.h"
#include"test03_BaseDataType.h"
#include"test04_Struct.h"
#include"test05_PointTo.h"
#include "test06_Oop.h"
#include "test10_ADTAndAlgorithms.h"
#include "test11_ADTOfLinearList.h"
#include "test12_ADTOfStack.h"
#include "test13_ADTOfQueue.h"
#include "test14_ADTOfTree.h"
#include "test14_ADTOfTreeRBTree.h"

#include "test15_ADTOfGraph.h"
#include "test16_AlgOfSearch.h"
#include "test17_AlgOfSort.h"

#include "test20_StlAbstract.h"
#include "test21_StlConOfVector.h"
#include "test22_StlConOfDeque.h"
#include "test23_StlConOfList.h"
#include "test24_StlConOfSet.h"
#include "test25_StlConOfMap.h"
#include "test26_StlConString.h"
#include "test27_StlConStack.h"
#include "test28_StlConTuple.h"
#include "test29_StlAlg.h"

//#include"test30_OpenCv.h"

#include "test40_ThreadTest.h"
#include "test41_MyUtilsSet.h"

// 说明
// 项目结构
// @1，一个主方法，其余按知识点分为若干个类，
// @2，数据的默认作用域为本类，如结构体等
// @3，每个类中有一个claMain（）方法作为调用本类的入口，类名为test0x_大驼峰的形式
// @4，特殊类会有相似的类名
// @5，外部文件中的函数的使用
//		#1 - 定义外部函数实现的cpp文件
//		#2 - 在主类中先声明，再使用

// winC++说明文档
// 来源
// https://docs.microsoft.com/zh-cn/cpp/cpp/ptr32-ptr64?view=vs-2019


using namespace std; // using编译指令，命名空间，保证命名不重复，放在函数内表示只在本函数内使用


// 在main执行之前可以执行的函数
// 全局变量、全局static变量是在程序加载后，main函数执行之前进行初始化的，借助这一特性，可以实现main之前执行特定函数
int func1() {
	cout << u8"func1()-main 函数执行之前可以执行的" << endl;
	return 0;
}
int func2() {
	cout << "func2()" << endl;
	return 0;
}

int i = func1();
static int j = func2();


int main(int argc, char* argv[]) // 函数头
// 一个类中只能有一个main函数
{
	// 解决控制台中文乱码
#ifdef _WIN32 // 条件编译指令#ifdef _WIN32，它用于判断当前代码是否在Windows平台上进行编译
	SetConsoleOutputCP(65001); //65001代表UTF-8，参见代码页标识符，在windows.h中
#endif
	//char sa = NULL;
	//scanf("%sa",sa); // C++ 可以使用所有C的标准输入输出函数，好像有错啊(winC++会对与c相同的函数做一些限制或修改)
	//printf("%sa", sa);
	printf("这是主类的 \n");
	cout << u8"入口文件的";
	cout << "主方法" << "\n"; // endl可用“\n”代替
	// printf是C中的标准输入输出函数，而cout是iostream类中的方法，是对运算符的重载

	std::cout << "<< " << endl; // endl表示光标重起一行，作用类似换行符\n
	// << 是对用算符的重载，编译器自动根据上下文判断符号的实际含义，C语言中 &和*也是重载，表示位运算和逻辑运算


	// 统一类实例的初始化
	test01::myNS::test01_Namespace t01me; // 嵌套namespace+class
	test02_MinExample t02me;
	test03_BaseDataType t03me;
	test04_Struct t04me; // 自动分配内存，作用域结束，自动回收
	// new 开辟堆内存
	// 类型 变量1，变量2 此种方式定义不同变量类型，存栈中
	test05_PointTo* te05me = new test05_PointTo(); // 手动分配内存，需要手动释放，一般在析构函数中调用 delete 释放
	//te05me->classMain();
	/*
	StructClass* ss = new StructClass(); 和 StructClass sa;的区别
		内存分配方式：对于ss指针所指向的对象，使用了动态内存分配，即在堆上分配了一块内存空间来存储StructClass对象。而sa是通过栈上的自动内存分配方式创建的，它会在其所在的作用域结束时自动被销毁。
		对象的生命周期：ss指针所指向的对象的生命周期由开发者手动管理，需要在不再使用时使用delete关键字释放对应的内存空间，以避免内存泄漏。而sa对象的生命周期由它所在的作用域决定，在作用域结束时会自动被销毁，无需手动释放内存。
		访问方式：对于ss指针所指向的对象，需要使用箭头操作符(->)来访问其成员变量和成员函数，例如ss->memberVariable、ss->memberFunction()。而对于sa对象，可以使用点操作符(.)来直接访问其成员变量和成员函数，例如sa.memberVariable、sa.memberFunction()
	*/

	test06_Oop* te06me = new test06_Oop();
	//te06me->classMain();


	test10_ADTAndAlgorithms* te10me = new test10_ADTAndAlgorithms();
	test11_ADTOfLinearList te11me;
	test12_ADTOfStack* te12me = new test12_ADTOfStack();
	test13_ADTOfQueue te13me;
	test14_ADTOfTree te14me;

	test15_ADTOfGraph te15me;
	test16_AlgOfSearch te16me;
	test17_AlgOfSort te17me;

	test20_StlAbstract te20me;
	test21_StlConOfVector te21me;
	test22_StlConOfDeque te22me;
	test23_StlConOfList te23me;
	test24_StlConOfSet te24me;
	test25_StlConOfMap te25me;
	test26_StlConString te26me;
	test27_StlConStack te27me;
	test28_StlConTuple te28me;
	test29_StlAlg te29me;

	//test30_OpenCv te30me;

	test40_ThreadTest te40me;
	test41_MyUtilsSet te41me;



	// 使用switch-case实现选择跳转
	int choice;
	printf("\n输入类编号: ");
	std::cin >> choice;
	//choice = getchar(); // char类型转成int
	//scanf_s("%d", &choice);
	//等待用户选择菜单项 = 0 退出
	while (1 && choice != 0) // && 逻辑与，&按位与
	{
		//根据用户不同的选择，调用相应的函数               
		switch (choice)
		{
		case 1:
			t01me.claMain();
			break;
		case 2:
			t02me.claMain();
			break;
		case 3:
			t03me.claMain();
			break;
		case 4:
			t04me.clsMain();
			break;
		case 5:
			te05me->classMain();
			break;
		case 6:
			te06me->classMain();
			break;
		case 10:
			te10me->classMain();
			break;
		case 11:
			te11me.classMain();
			break;
		case 12:
			te12me->classMain();
			break;
		case 13:
			te13me.classMain();
			break;
		case 14:
			te14me.classMain();
			break;
		case 15:
			te15me.classMain();
			break;
		case 16:
			te16me.classMain();
			break;
		case 17:
			te17me.classMain();
			break;

		case 20:
			te20me.classMain();
			break;
		case 21:
			te21me.classMain();
			break;
		case 22:
			te22me.classMain();
			break;
		case 23:
			te23me.classMain();
			break;
		case 24:
			te24me.classMain();
			break;
		case 25:
			te25me.classMain();
			break;
		case 26:
			te26me.classMain();
			break;
		case 27:
			te27me.classMain();
			break;
		case 28:
			te28me.classMain();
			break;
		case 29:
			te29me.classMain();
			break;

			//
			//case 30:
			//	te30me.classMain();
			//	break;

		case 40:
			te40me.classMain();
			break;
		case 41:
			te41me.classMain();
			break;


		default:
			printf("\n无效的输入!\n");
		}
		printf("\n输入类编号: ");
		std::cin >> choice;
		//scanf_s("%d", &choice);
	}

	// 手动释放空间
	delete te12me;
	return 0;
}
